package com.fractalist.base.core.utils;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * <p>
 * Name：BolsterRefection.java
 * </p>
 * <p>
 * Title: FTWX APPSBolster
 * </p>
 * <p>
 * Description：
 * </p>
 * <p>
 * Copyright (c) 2012-05-30 by FTWX
 * 
 * @author sam
 * @version 1.0 CreateTime：2012-05-30 14:58:07
 *          </p>
 */
public class BolsterRefection {

	/**
	 * 通过反射,获得Class定义中声明的父类的泛型参数的类型. 如无法找到, 返回Object.class. eg. public UserDao
	 * extends HibernateDao<User>
	 * 
	 * @param clazz
	 *            The class to introspect
	 * @return the first generic declaration, or Object.class if cannot be
	 *         determined
	 */
	@SuppressWarnings("unchecked")
	public static <T> Class<T> getSuperClassGenricType(final Class clazz) {
		return getSuperClassGenricType(clazz, 0);
	}

	/**
	 * 通过反射,获得定义Class时声明的父类的泛型参数的类型. 如无法找到, 返回Object.class.
	 * 
	 * 如public UserDao extends HibernateDao<User,Long>
	 * 
	 * @param clazz
	 *            clazz The class to introspect
	 * @param index
	 *            the Index of the generic ddeclaration,start from 0.
	 * @return the index generic declaration, or Object.class if cannot be
	 *         determined
	 */
	@SuppressWarnings("unchecked")
	public static Class getSuperClassGenricType(final Class clazz,
			final int index) {

		Type genType = clazz.getGenericSuperclass();

		if (!(genType instanceof ParameterizedType)) {
			// logger.warn(clazz.getSimpleName()
			// + "'s superclass not ParameterizedType");
			return Object.class;
		}

		Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

		if (index >= params.length || index < 0) {
			// logger.warn("Index: " + index + ", Size of "
			// + clazz.getSimpleName() + "'s Parameterized Type: "
			// + params.length);
			return Object.class;
		}
		if (!(params[index] instanceof Class)) {
			// logger
			// .warn(clazz.getSimpleName()
			// + " not set the actual class on superclass generic parameter");
			return Object.class;
		}

		return (Class) params[index];
	}

	/**
	 * 得到某个对象的公共属性
	 * 
	 * @param owner
	 *            , fieldName
	 * @return 该属性对象
	 * @throws Exception
	 * 
	 */
	@SuppressWarnings("unchecked")
	public Object getProperty(Object owner, String fieldName) throws Exception {
		Class ownerClass = owner.getClass();

		Field field = ownerClass.getField(fieldName);

		Object property = field.get(owner);

		return property;
	}

	/**
	 * 得到某类的静态公共属性
	 * 
	 * @param className
	 *            类名
	 * @param fieldName
	 *            属性名
	 * @return 该属性对象
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public Object getStaticProperty(String className, String fieldName)
			throws Exception {
		Class ownerClass = Class.forName(className);

		Field field = ownerClass.getField(fieldName);

		Object property = field.get(ownerClass);

		return property;
	}

	/**
	 * 执行某对象方法
	 * 
	 * @param owner
	 *            对象
	 * @param methodName
	 *            方法名
	 * @param args
	 *            参数
	 * @return 方法返回值
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public Object invokeMethod(Object owner, String methodName, Object[] args)
			throws Exception {

		Class ownerClass = owner.getClass();
		if (null == args) {
			Class[] argsClass = null;
			Method method = ownerClass.getMethod(methodName, argsClass);
			return method.invoke(owner, args);
		} else {
			Class[] argsClass = new Class[args.length];
			for (int i = 0, j = args.length; i < j; i++) {
				argsClass[i] = args[i].getClass();
				if (argsClass[i].toString().indexOf("NioSocketSession") > 0) {
					// argsClass[i] = org.apache.mina.common.IoSession.class;
				}
				// System.out.println(argsClass[i]);
			}
			Method method = ownerClass.getMethod(methodName, argsClass);
			return method.invoke(owner, args);
		}
	}

	/**
	 * 执行某类的静态方法
	 * 
	 * @param className
	 *            类名
	 * @param methodName
	 *            方法名
	 * @param args
	 *            参数数组
	 * @return 执行方法返回的结果
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public Object invokeStaticMethod(String className, String methodName,
			Object[] args) throws Exception {
		Class ownerClass = Class.forName(className);

		Class[] argsClass = new Class[args.length];

		for (int i = 0, j = args.length; i < j; i++) {
			argsClass[i] = args[i].getClass();
		}

		Method method = ownerClass.getMethod(methodName, argsClass);

		return method.invoke(null, args);
	}

	/**
	 * 新建实例
	 * 
	 * @param className
	 *            类名
	 * @param args
	 *            构造函数的参数
	 * @return 新建的实例
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public Object newInstance(String className, Object[] args) throws Exception {
		Class newoneClass = Class.forName(className);
		if (null != args) {
			Class[] argsClass = new Class[args.length];
			for (int i = 0, j = args.length; i < j; i++) {
				argsClass[i] = args[i].getClass();
			}
			Constructor cons = newoneClass.getConstructor(argsClass);
			return cons.newInstance(args);
		} else {
			Constructor cons = newoneClass.getConstructor();
			return cons.newInstance(args);
		}
	}

	/**
	 * 
	 * @param className
	 * @param args
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public Object newInstance(Class newoneClass, Object[] args)
			throws Exception {
		if (null != args) {
			Class[] argsClass = new Class[args.length];
			for (int i = 0, j = args.length; i < j; i++) {
				argsClass[i] = args[i].getClass();
			}
			Constructor cons = newoneClass.getConstructor(argsClass);
			return cons.newInstance(args);
		} else {
			Constructor cons = newoneClass.getConstructor();
			return cons.newInstance(args);
		}
	}

	/**
	 * 是不是某个类的实例
	 * 
	 * @param obj
	 *            实例
	 * @param cls
	 *            类
	 * @return 如果 obj 是此类的实例，则返回 true
	 */

	public boolean isInstance(Object obj, Class cls) {
		return cls.isInstance(obj);
	}

	/**
	 * 得到数组中的某个元素
	 * 
	 * @param array
	 *            数组
	 * @param index
	 *            索引
	 * @return 返回指定数组对象中索引组件的值
	 */
	public Object getByArray(Object array, int index) {
		return Array.get(array, index);
	}
}
